package org.glavo.bot.data

import kotlinx.serialization.json.Json
import kotlinx.serialization.json.JsonElement
import java.nio.file.Paths
import java.util.NoSuchElementException
import java.util.zip.ZipEntry
import java.util.zip.ZipInputStream
import kotlin.io.path.absolute
import kotlin.io.path.inputStream
import kotlin.io.path.notExists

object Data {
    private fun readData(): Map<String, ByteArray> {
        val dataJar = Paths.get("data.jar").absolute()
        if (dataJar.notExists()) {
            error("$dataJar not exists")
        }

        val res = mutableMapOf<String, ByteArray>()

        ZipInputStream(dataJar.inputStream()).use { zip ->
            var entry: ZipEntry?

            while (true) {
                entry = zip.nextEntry
                if (entry == null) {
                    break
                }

                if (!entry.isDirectory) {
                    res[entry.name] = zip.readAllBytes()
                }
            }
        }

        return res
    }

    @Volatile
    var data: Map<String, ByteArray> = readData()
        private set

    val jsonFormat = Json {
        isLenient = true
        ignoreUnknownKeys = true
    }

    fun reload() {
        synchronized(Data) {
            data = readData()

            Minecraft.reload()
            Advancements.reload()
            Death.reload()
            Player.reload()
            Mirrors.reload()
            System.gc()
        }

    }

    fun readResource(resource: String): ByteArray =
        data.getOrElse(resource) { throw NoSuchElementException("resource=$resource") }

    fun readResourceAsText(resource: String): String {
        return String(readResource(resource))
    }

    fun readJson(resource: String): JsonElement = Json.parseToJsonElement(readResourceAsText(resource))
}